/**
 * @see java.util.concurrent.locks.AbstractQueuedSynchronizer
 * AQS：AbstractQueuedSynchronizer 抽象的队列式同步器。是除了java自带的synchronized关键字之外的锁机制。
 *  基于CLH（Craig，Landin，and Hagersten）队列算法，维护请求共享资源线程
 *  基于CAS去改变状态符，成功则线程获取锁，失败则等待
 *
 **注：AQS是自旋锁：**在等待唤醒的时候，经常会使用自旋（while(!cas())）的方式，不停地尝试获取锁，直到被其他线程获取成功
 *
 * AQS的核心思想是，如果被请求的共享资源空闲，则将当前请求资源的线程设置为有效的工作线程，并将共享资源设置为锁定状态，如果被请求的共享资源被占用，那么就需要一套线程阻塞等待以及被唤醒时锁分配的机制，这个机制AQS是用CLH队列锁实现的，即将暂时获取不到锁的线程加入到队列中。
 * CLH（Craig，Landin，and Hagersten）队列是一个虚拟的双向队列，虚拟的双向队列即不存在队列实例，仅存在节点之间的关联关系。
 * AQS是将每一条请求共享资源的线程封装成一个CLH锁队列的一个结点（Node），来实现锁的分配。
 *
 * 用大白话来说，AQS就是基于CLH队列，用volatile修饰共享变量state，线程通过CAS去改变状态符，成功则获取锁成功，失败则进入等待队列，等待被唤醒。
 *
 *
 * 实现了AQS的锁有：自旋锁、互斥锁、读锁写锁、条件产量、信号量、栅栏都是AQS的衍生物
 * AbstractQueuedSynchronizer
 *     java.util.concurrent.Semaphore.Sync
 *     java.util.concurrent.locks.ReentrantLock.Sync
 *     java.util.concurrent.locks.ReentrantReadWriteLock.Sync
 *
 *
 *
 * 自选锁的坏处:
 *   线程轮询
 * 自旋锁的好处：
 *   自旋锁的使用是有场景的，在我们的程序中，如果存在着大量的互斥同步代码，当出现高并发的时候，系统内核态就需要不断的去挂起线程和恢复线程，
 * 频繁的此类操作会对我们系统的并发性能有一定影响。
 * 在程序的执行过程中锁定“共享资源“的时间片是极短的，如果仅仅是为了这点时间而去不断挂起、恢复线程的话，
 * 消耗的时间可能会更长，为了避免频繁的线程切换，在JDK中引入了大量的自旋锁程序。
 */
package cn.jdemo.juc.AQS;